home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / light.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  43.9 KB  |  1,379 lines

  1. /* $Id: light.c,v 1.7 1997/03/11 00:37:39 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: light.c,v $
  26.  * Revision 1.7  1997/03/11 00:37:39  brianp
  27.  * spotlight factor now effects ambient lighting
  28.  *
  29.  * Revision 1.6  1996/12/18 20:02:07  brianp
  30.  * glColorMaterial() and glMaterial() should finally work right!
  31.  *
  32.  * Revision 1.5  1996/12/07 10:22:41  brianp
  33.  * gl_Materialfv() now calls gl_set_material() if GL_COLOR_MATERIAL disabled
  34.  * implemented gl_GetLightiv()
  35.  *
  36.  * Revision 1.4  1996/11/08 04:39:23  brianp
  37.  * new gl_compute_spot_exp_table() contributed by Randy Frank
  38.  *
  39.  * Revision 1.3  1996/09/27 01:27:55  brianp
  40.  * removed unused variables
  41.  *
  42.  * Revision 1.2  1996/09/15 14:18:10  brianp
  43.  * now use GLframebuffer and GLvisual
  44.  *
  45.  * Revision 1.1  1996/09/13 01:38:16  brianp
  46.  * Initial revision
  47.  *
  48.  */
  49.  
  50.  
  51. #include <assert.h>
  52. #include <float.h>
  53. #include <math.h>
  54. #include <stdlib.h>
  55. #include "context.h"
  56. #include "light.h"
  57. #include "dlist.h"
  58. #include "macros.h"
  59. #include "matrix.h"
  60. #include "types.h"
  61. #include "vb.h"
  62. #include "xform.h"
  63.  
  64.  
  65. #ifdef DEBUG
  66. #  define ASSERT(X)  assert(X)
  67. #else
  68. #  define ASSERT(X)
  69. #endif
  70.  
  71.  
  72. #define DEG2RAD (M_PI/180.0)
  73.  
  74.  
  75.  
  76. void gl_ShadeModel( GLcontext *ctx, GLenum mode )
  77. {
  78.    if (INSIDE_BEGIN_END(ctx)) {
  79.       gl_error( ctx, GL_INVALID_OPERATION, "glShadeModel" );
  80.       return;
  81.    }
  82.  
  83.    switch (mode) {
  84.       case GL_FLAT:
  85.       case GL_SMOOTH:
  86.          if (ctx->Light.ShadeModel!=mode) {
  87.             ctx->Light.ShadeModel = mode;
  88.             ctx->NewState |= NEW_RASTER_OPS;
  89.          }
  90.          break;
  91.       default:
  92.          gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
  93.    }
  94. }
  95.  
  96.  
  97.  
  98. void gl_Lightfv( GLcontext *ctx,
  99.                  GLenum light, GLenum pname, const GLfloat *params,
  100.                  GLint nparams )
  101. {
  102.    GLint l;
  103.  
  104.    if (INSIDE_BEGIN_END(ctx)) {
  105.       gl_error( ctx, GL_INVALID_OPERATION, "glShadeModel" );
  106.       return;
  107.    }
  108.  
  109.    l = (GLint) (light - GL_LIGHT0);
  110.  
  111.    if (l<0 || l>=MAX_LIGHTS) {
  112.       gl_error( ctx, GL_INVALID_ENUM, "glLight" );
  113.       return;
  114.    }
  115.  
  116.    switch (pname) {
  117.       case GL_AMBIENT:
  118.          COPY_4V( ctx->Light.Light[l].Ambient, params );
  119.          break;
  120.       case GL_DIFFUSE:
  121.          COPY_4V( ctx->Light.Light[l].Diffuse, params );
  122.          break;
  123.       case GL_SPECULAR:
  124.          COPY_4V( ctx->Light.Light[l].Specular, params );
  125.          break;
  126.       case GL_POSITION:
  127.      /* transform position by ModelView matrix */
  128.      TRANSFORM_POINT( ctx->Light.Light[l].Position, ctx->ModelViewMatrix,
  129.                           params );
  130.          break;
  131.       case GL_SPOT_DIRECTION:
  132.      /* transform direction by inverse modelview */
  133.          {
  134.             GLfloat direction[4];
  135.             direction[0] = params[0];
  136.             direction[1] = params[1];
  137.             direction[2] = params[2];
  138.             direction[3] = 0.0;
  139.             if (!ctx->ModelViewInvValid) {
  140.                gl_compute_modelview_inverse( ctx );
  141.             }
  142.             gl_transform_vector( ctx->Light.Light[l].Direction,
  143.                                  direction, ctx->ModelViewInv);
  144.          }
  145.          break;
  146.       case GL_SPOT_EXPONENT:
  147.          if (params[0]<0.0 || params[0]>128.0) {
  148.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  149.             return;
  150.          }
  151.          ctx->Light.Light[l].SpotExponent = params[0];
  152.          gl_compute_spot_exp_table( &ctx->Light.Light[l] );
  153.          break;
  154.       case GL_SPOT_CUTOFF:
  155.          if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
  156.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  157.             return;
  158.          }
  159.          ctx->Light.Light[l].SpotCutoff = params[0];
  160.          ctx->Light.Light[l].CosCutoff = cos(params[0]*DEG2RAD);
  161.          break;
  162.       case GL_CONSTANT_ATTENUATION:
  163.          if (params[0]<0.0) {
  164.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  165.             return;
  166.          }
  167.          ctx->Light.Light[l].ConstantAttenuation = params[0];
  168.          break;
  169.       case GL_LINEAR_ATTENUATION:
  170.          if (params[0]<0.0) {
  171.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  172.             return;
  173.          }
  174.          ctx->Light.Light[l].LinearAttenuation = params[0];
  175.          break;
  176.       case GL_QUADRATIC_ATTENUATION:
  177.          if (params[0]<0.0) {
  178.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  179.             return;
  180.          }
  181.          ctx->Light.Light[l].QuadraticAttenuation = params[0];
  182.          break;
  183.       default:
  184.          gl_error( ctx, GL_INVALID_ENUM, "glLight" );
  185.          break;
  186.    }
  187.  
  188.    ctx->NewState |= NEW_LIGHTING;
  189. }
  190.  
  191.  
  192.  
  193. void gl_GetLightfv( GLcontext *ctx,
  194.                     GLenum light, GLenum pname, GLfloat *params )
  195. {
  196.    GLint l = (GLint) (light - GL_LIGHT0);
  197.  
  198.    if (l<0 || l>=MAX_LIGHTS) {
  199.       gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
  200.       return;
  201.    }
  202.  
  203.    switch (pname) {
  204.       case GL_AMBIENT:
  205.          COPY_4V( params, ctx->Light.Light[l].Ambient );
  206.          break;
  207.       case GL_DIFFUSE:
  208.          COPY_4V( params, ctx->Light.Light[l].Diffuse );
  209.          break;
  210.       case GL_SPECULAR:
  211.          COPY_4V( params, ctx->Light.Light[l].Specular );
  212.          break;
  213.       case GL_POSITION:
  214.          COPY_4V( params, ctx->Light.Light[l].Position );
  215.          break;
  216.       case GL_SPOT_DIRECTION:
  217.          COPY_3V( params, ctx->Light.Light[l].Direction );
  218.          break;
  219.       case GL_SPOT_EXPONENT:
  220.          params[0] = ctx->Light.Light[l].SpotExponent;
  221.          break;
  222.       case GL_SPOT_CUTOFF:
  223.          params[0] = ctx->Light.Light[l].SpotCutoff;
  224.          break;
  225.       case GL_CONSTANT_ATTENUATION:
  226.          params[0] = ctx->Light.Light[l].ConstantAttenuation;
  227.          break;
  228.       case GL_LINEAR_ATTENUATION:
  229.          params[0] = ctx->Light.Light[l].LinearAttenuation;
  230.          break;
  231.       case GL_QUADRATIC_ATTENUATION:
  232.          params[0] = ctx->Light.Light[l].QuadraticAttenuation;
  233.          break;
  234.       default:
  235.          gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
  236.          break;
  237.    }
  238. }
  239.  
  240.  
  241.  
  242. void gl_GetLightiv( GLcontext *ctx, GLenum light, GLenum pname, GLint *params )
  243. {
  244.    GLint l = (GLint) (light - GL_LIGHT0);
  245.  
  246.    if (l<0 || l>=MAX_LIGHTS) {
  247.       gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
  248.       return;
  249.    }
  250.  
  251.    switch (pname) {
  252.       case GL_AMBIENT:
  253.          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
  254.          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
  255.          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
  256.          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
  257.          break;
  258.       case GL_DIFFUSE:
  259.          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
  260.          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
  261.          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
  262.          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
  263.          break;
  264.       case GL_SPECULAR:
  265.          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
  266.          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
  267.          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
  268.          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
  269.          break;
  270.       case GL_POSITION:
  271.          params[0] = ctx->Light.Light[l].Position[0];
  272.          params[1] = ctx->Light.Light[l].Position[1];
  273.          params[2] = ctx->Light.Light[l].Position[2];
  274.          params[3] = ctx->Light.Light[l].Position[3];
  275.          break;
  276.       case GL_SPOT_DIRECTION:
  277.          params[0] = ctx->Light.Light[l].Direction[0];
  278.          params[1] = ctx->Light.Light[l].Direction[1];
  279.          params[2] = ctx->Light.Light[l].Direction[2];
  280.          break;
  281.       case GL_SPOT_EXPONENT:
  282.          params[0] = ctx->Light.Light[l].SpotExponent;
  283.          break;
  284.       case GL_SPOT_CUTOFF:
  285.          params[0] = ctx->Light.Light[l].SpotCutoff;
  286.          break;
  287.       case GL_CONSTANT_ATTENUATION:
  288.          params[0] = ctx->Light.Light[l].ConstantAttenuation;
  289.          break;
  290.       case GL_LINEAR_ATTENUATION:
  291.          params[0] = ctx->Light.Light[l].LinearAttenuation;
  292.          break;
  293.       case GL_QUADRATIC_ATTENUATION:
  294.          params[0] = ctx->Light.Light[l].QuadraticAttenuation;
  295.          break;
  296.       default:
  297.          gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
  298.          break;
  299.    }
  300. }
  301.  
  302.  
  303.  
  304. /**********************************************************************/
  305. /***                        Light Model                             ***/
  306. /**********************************************************************/
  307.  
  308.  
  309. void gl_LightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
  310. {
  311.    switch (pname) {
  312.       case GL_LIGHT_MODEL_AMBIENT:
  313.          COPY_4V( ctx->Light.Model.Ambient, params );
  314.          break;
  315.       case GL_LIGHT_MODEL_LOCAL_VIEWER:
  316.          if (params[0]==0.0)
  317.             ctx->Light.Model.LocalViewer = GL_FALSE;
  318.          else
  319.             ctx->Light.Model.LocalViewer = GL_TRUE;
  320.          break;
  321.       case GL_LIGHT_MODEL_TWO_SIDE:
  322.          if (params[0]==0.0)
  323.             ctx->Light.Model.TwoSide = GL_FALSE;
  324.          else
  325.             ctx->Light.Model.TwoSide = GL_TRUE;
  326.          break;
  327.       default:
  328.          gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
  329.          break;
  330.    }
  331.    ctx->NewState |= NEW_LIGHTING;
  332. }
  333.  
  334.  
  335.  
  336.  
  337. /********** MATERIAL **********/
  338.  
  339.  
  340. /*
  341.  * Given a face and pname value (ala glColorMaterial), compute a bitmask
  342.  * of the targeted material values.
  343.  */
  344. GLuint gl_material_bitmask( GLenum face, GLenum pname )
  345. {
  346.    GLuint bitmask = 0;
  347.  
  348.    /* Make a bitmask indicating what material attribute(s) we're updating */
  349.    switch (pname) {
  350.       case GL_EMISSION:
  351.          bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
  352.          break;
  353.       case GL_AMBIENT:
  354.          bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
  355.          break;
  356.       case GL_DIFFUSE:
  357.          bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
  358.          break;
  359.       case GL_SPECULAR:
  360.          bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
  361.          break;
  362.       case GL_SHININESS:
  363.          bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
  364.          break;
  365.       case GL_AMBIENT_AND_DIFFUSE:
  366.          bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
  367.          bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
  368.          break;
  369.       case GL_COLOR_INDEXES:
  370.          bitmask |= FRONT_INDEXES_BIT  | BACK_INDEXES_BIT;
  371.          break;
  372.       default:
  373.          abort();
  374.    }
  375.  
  376.    ASSERT( face==GL_FRONT || face==GL_BACK || face==GL_FRONT_AND_BACK );
  377.  
  378.    if (face==GL_FRONT) {
  379.       bitmask &= FRONT_MATERIAL_BITS;
  380.    }
  381.    else if (face==GL_BACK) {
  382.       bitmask &= BACK_MATERIAL_BITS;
  383.    }
  384.  
  385.    return bitmask;
  386. }
  387.  
  388.  
  389.  
  390. /*
  391.  * This is called by glColor() when GL_COLOR_MATERIAL is enabled and
  392.  * called by glMaterial() when GL_COLOR_MATERIAL is disabled.
  393.  */
  394. void gl_set_material( GLcontext *ctx, GLuint bitmask, const GLfloat *params )
  395. {
  396.    struct gl_material *mat;
  397.  
  398.    if (INSIDE_BEGIN_END(ctx)) {
  399.       struct vertex_buffer *VB = ctx->VB;
  400.       /* Save per-vertex material changes in the Vertex Buffer.
  401.        * The update_material function will eventually update the global
  402.        * ctx->Light.Material values.
  403.        */
  404.       mat = VB->Material[VB->Count];
  405.       VB->MaterialMask[VB->Count] |= bitmask;
  406.       VB->MaterialChanges = GL_TRUE;
  407.    }
  408.    else {
  409.       /* just update the global material property */
  410.       mat = ctx->Light.Material;
  411.       ctx->NewState |= NEW_LIGHTING;
  412.    }
  413.  
  414.    if (bitmask & FRONT_AMBIENT_BIT) {
  415.       COPY_4V( mat[0].Ambient, params );
  416.    }
  417.    if (bitmask & BACK_AMBIENT_BIT) {
  418.       COPY_4V( mat[1].Ambient, params );
  419.    }
  420.    if (bitmask & FRONT_DIFFUSE_BIT) {
  421.       COPY_4V( mat[0].Diffuse, params );
  422.    }
  423.    if (bitmask & BACK_DIFFUSE_BIT) {
  424.       COPY_4V( mat[1].Diffuse, params );
  425.    }
  426.    if (bitmask & FRONT_SPECULAR_BIT) {
  427.       COPY_4V( mat[0].Specular, params );
  428.    }
  429.    if (bitmask & BACK_SPECULAR_BIT) {
  430.       COPY_4V( mat[1].Specular, params );
  431.    }
  432.    if (bitmask & FRONT_EMISSION_BIT) {
  433.       COPY_4V( mat[0].Emission, params );
  434.    }
  435.    if (bitmask & BACK_EMISSION_BIT) {
  436.       COPY_4V( mat[1].Emission, params );
  437.    }
  438.    if (bitmask & FRONT_SHININESS_BIT) {
  439.       mat[0].Shininess = CLAMP( params[0], 0.0, 128.0 );
  440.       gl_compute_material_shine_table( &mat[0] );
  441.    }
  442.    if (bitmask & BACK_SHININESS_BIT) {
  443.       mat[1].Shininess = CLAMP( params[0], 0.0, 128.0 );
  444.       gl_compute_material_shine_table( &mat[1] );
  445.    }
  446.    if (bitmask & FRONT_INDEXES_BIT) {
  447.       mat[0].AmbientIndex = params[0];
  448.       mat[0].DiffuseIndex = params[1];
  449.       mat[0].SpecularIndex = params[2];
  450.    }
  451.    if (bitmask & BACK_INDEXES_BIT) {
  452.       mat[1].AmbientIndex = params[0];
  453.       mat[1].DiffuseIndex = params[1];
  454.       mat[1].SpecularIndex = params[2];
  455.    }
  456. }
  457.  
  458.  
  459.  
  460. void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
  461. {
  462.    if (INSIDE_BEGIN_END(ctx)) {
  463.       gl_error( ctx, GL_INVALID_OPERATION, "glColorMaterial" );
  464.       return;
  465.    }
  466.    switch (face) {
  467.       case GL_FRONT:
  468.       case GL_BACK:
  469.       case GL_FRONT_AND_BACK:
  470.          ctx->Light.ColorMaterialFace = face;
  471.          break;
  472.       default:
  473.          gl_error( ctx, GL_INVALID_ENUM, "glColorMaterial(face)" );
  474.          return;
  475.    }
  476.    switch (mode) {
  477.       case GL_EMISSION:
  478.       case GL_AMBIENT:
  479.       case GL_DIFFUSE:
  480.       case GL_SPECULAR:
  481.       case GL_AMBIENT_AND_DIFFUSE:
  482.          ctx->Light.ColorMaterialMode = mode;
  483.          break;
  484.       default:
  485.          gl_error( ctx, GL_INVALID_ENUM, "glColorMaterial(mode)" );
  486.          return;
  487.    }
  488.  
  489.    ctx->Light.ColorMaterialBitmask = gl_material_bitmask( face, mode );
  490. }
  491.  
  492.  
  493.  
  494. /*
  495.  * This is only called via the api_function_table struct or by the
  496.  * display list executor.
  497.  */
  498. void gl_Materialfv( GLcontext *ctx,
  499.                     GLenum face, GLenum pname, const GLfloat *params )
  500. {
  501.    GLuint bitmask;
  502.  
  503.    /* error checking */
  504.    if (face!=GL_FRONT && face!=GL_BACK && face!=GL_FRONT_AND_BACK) {
  505.       gl_error( ctx, GL_INVALID_ENUM, "glMaterial(face)" );
  506.       return;
  507.    }
  508.    switch (pname) {
  509.       case GL_EMISSION:
  510.       case GL_AMBIENT:
  511.       case GL_DIFFUSE:
  512.       case GL_SPECULAR:
  513.       case GL_SHININESS:
  514.       case GL_AMBIENT_AND_DIFFUSE:
  515.       case GL_COLOR_INDEXES:
  516.          /* OK */
  517.          break;
  518.       default:
  519.          gl_error( ctx, GL_INVALID_ENUM, "glMaterial(pname)" );
  520.          return;
  521.    }
  522.  
  523.    /* convert face and pname to a bitmask */
  524.    bitmask = gl_material_bitmask( face, pname );
  525.  
  526.    if (ctx->Light.ColorMaterialEnabled) {
  527.       /* The material values specified by glColorMaterial() can't be */
  528.       /* updated by glMaterial() while GL_COLOR_MATERIAL is enabled! */
  529.       bitmask &= ~ctx->Light.ColorMaterialBitmask;
  530.    }
  531.  
  532.    gl_set_material( ctx, bitmask, params );
  533. }
  534.  
  535.  
  536.  
  537.  
  538. void gl_GetMaterialfv( GLcontext *ctx,
  539.                        GLenum face, GLenum pname, GLfloat *params )
  540. {
  541.    GLuint f;
  542.  
  543.    if (INSIDE_BEGIN_END(ctx)) {
  544.       gl_error( ctx, GL_INVALID_OPERATION, "glGetMaterialfv" );
  545.       return;
  546.    }
  547.    if (face==GL_FRONT) {
  548.       f = 0;
  549.    }
  550.    else if (face==GL_BACK) {
  551.       f = 1;
  552.    }
  553.    else {
  554.       gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
  555.       return;
  556.    }
  557.    switch (pname) {
  558.       case GL_AMBIENT:
  559.          COPY_4V( params, ctx->Light.Material[f].Ambient );
  560.          break;
  561.       case GL_DIFFUSE:
  562.          COPY_4V( params, ctx->Light.Material[f].Diffuse );
  563.      break;
  564.       case GL_SPECULAR:
  565.          COPY_4V( params, ctx->Light.Material[f].Specular );
  566.      break;
  567.       case GL_EMISSION:
  568.      COPY_4V( params, ctx->Light.Material[f].Emission );
  569.      break;
  570.       case GL_SHININESS:
  571.      *params = ctx->Light.Material[f].Shininess;
  572.      break;
  573.       case GL_COLOR_INDEXES:
  574.      params[0] = ctx->Light.Material[f].AmbientIndex;
  575.      params[1] = ctx->Light.Material[f].DiffuseIndex;
  576.      params[2] = ctx->Light.Material[f].SpecularIndex;
  577.      break;
  578.       default:
  579.          gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
  580.    }
  581. }
  582.  
  583.  
  584.  
  585. void gl_GetMaterialiv( GLcontext *ctx,
  586.                        GLenum face, GLenum pname, GLint *params )
  587. {
  588.    GLuint f;
  589.  
  590.    if (INSIDE_BEGIN_END(ctx)) {
  591.       gl_error( ctx, GL_INVALID_OPERATION, "glGetMaterialiv" );
  592.       return;
  593.    }
  594.    if (face==GL_FRONT) {
  595.       f = 0;
  596.    }
  597.    else if (face==GL_BACK) {
  598.       f = 1;
  599.    }
  600.    else {
  601.       gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
  602.       return;
  603.    }
  604.    switch (pname) {
  605.       case GL_AMBIENT:
  606.          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] );
  607.          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] );
  608.          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] );
  609.          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] );
  610.          break;
  611.       case GL_DIFFUSE:
  612.          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] );
  613.          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] );
  614.          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] );
  615.          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] );
  616.      break;
  617.       case GL_SPECULAR:
  618.          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] );
  619.          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] );
  620.          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] );
  621.          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] );
  622.      break;
  623.       case GL_EMISSION:
  624.          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] );
  625.          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] );
  626.          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] );
  627.          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] );
  628.      break;
  629.       case GL_SHININESS:
  630.          *params = ROUNDF( ctx->Light.Material[f].Shininess );
  631.      break;
  632.       case GL_COLOR_INDEXES:
  633.      params[0] = ROUNDF( ctx->Light.Material[f].AmbientIndex );
  634.      params[1] = ROUNDF( ctx->Light.Material[f].DiffuseIndex );
  635.      params[2] = ROUNDF( ctx->Light.Material[f].SpecularIndex );
  636.      break;
  637.       default:
  638.          gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
  639.    }
  640. }
  641.  
  642.  
  643.  
  644.  
  645. /**********************************************************************/
  646. /*****                  Lighting computation                      *****/
  647. /**********************************************************************/
  648.  
  649.  
  650. /*
  651.  * Notes:
  652.  *   When two-sided lighting is enabled we compute the color (or index)
  653.  *   for both the front and back side of the primitive.  Then, when the
  654.  *   orientation of the facet is later learned, we can determine which
  655.  *   color (or index) to use for rendering.
  656.  *
  657.  * Variables:
  658.  *   n = normal vector
  659.  *   V = vertex position
  660.  *   P = light source position
  661.  *   Pe = (0,0,0,1)
  662.  *
  663.  * Precomputed:
  664.  *   IF P[3]==0 THEN
  665.  *       // light at infinity
  666.  *       IF local_viewer THEN
  667.  *           VP_inf_norm = unit vector from V to P      // Precompute
  668.  *       ELSE 
  669.  *           // eye at infinity
  670.  *           h_inf_norm = Normalize( VP + <0,0,1> )     // Precompute
  671.  *       ENDIF
  672.  *   ENDIF
  673.  *
  674.  * Functions:
  675.  *   Normalize( v ) = normalized vector v
  676.  *   Magnitude( v ) = length of vector v
  677.  */
  678.  
  679.  
  680.  
  681. /*
  682.  * Whenever the spotlight exponent for a light changes we must call
  683.  * this function to recompute the exponent lookup table.
  684.  */
  685. void gl_compute_spot_exp_table( struct gl_light *l )
  686. {
  687.    int i;
  688.    double exponent = l->SpotExponent;
  689.    double tmp;
  690.    int clamp = 0;
  691.  
  692.    l->SpotExpTable[0][0] = 0.0;
  693.  
  694.    for (i=EXP_TABLE_SIZE-1;i>0;i--) {
  695.       if (clamp == 0) {
  696.          tmp = pow(i/(double)(EXP_TABLE_SIZE-1), exponent);
  697.          if (tmp < FLT_MIN*100.0) {
  698.             tmp = 0.0;
  699.             clamp = 1;
  700.          }
  701.       }
  702.       l->SpotExpTable[i][0] = tmp;
  703.    }
  704.    for (i=0;i<EXP_TABLE_SIZE-1;i++) {
  705.       l->SpotExpTable[i][1] = l->SpotExpTable[i+1][0] - l->SpotExpTable[i][0];
  706.    }
  707.    l->SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
  708. }
  709.  
  710.  
  711.  
  712. /*
  713.  * Whenever the shininess of a material changes we must call this
  714.  * function to recompute the exponential lookup table.
  715.  */
  716. void gl_compute_material_shine_table( struct gl_material *m )
  717. {
  718.    int i;
  719.    double exponent = m->Shininess;
  720.  
  721.    m->ShineTable[0] = 0.0;
  722.    for (i=1;i<SHINE_TABLE_SIZE;i++) {
  723.       double x = pow( i/(double)(SHINE_TABLE_SIZE-1), exponent );
  724.       if (x<1.0e-10) {
  725.          m->ShineTable[i] = 0.0;
  726.       }
  727.       else {
  728.          m->ShineTable[i] = x;
  729.       }
  730.    }
  731. }
  732.  
  733.  
  734.  
  735. /*
  736.  * Examine current lighting parameters to determine if the optimized lighting
  737.  * function can be used.  Also, precompute some lighting values which are
  738.  * used by gl_color_shade_vertices_fast().
  739.  */
  740. void gl_update_lighting( GLcontext *ctx )
  741. {
  742.    GLint i;
  743.    struct gl_light *prev_enabled, *light;
  744.  
  745.    if (!ctx->Light.Enabled) {
  746.       /* If lighting is not enabled, we can skip all this. */
  747.       return;
  748.    }
  749.  
  750.    /* base color = material_emission + global_ambient */
  751.    ctx->Light.BaseColor[0] = ctx->Light.Material[0].Emission[0]
  752.              + ctx->Light.Model.Ambient[0] * ctx->Light.Material[0].Ambient[0];
  753.    ctx->Light.BaseColor[1] = ctx->Light.Material[0].Emission[1]
  754.              + ctx->Light.Model.Ambient[1] * ctx->Light.Material[0].Ambient[1];
  755.    ctx->Light.BaseColor[2] = ctx->Light.Material[0].Emission[2]
  756.              + ctx->Light.Model.Ambient[2] * ctx->Light.Material[0].Ambient[2];
  757.    ctx->Light.BaseColor[3] = MIN2( ctx->Light.Material[0].Diffuse[3], 1.0F );
  758.  
  759.    /* Setup linked list of enabled light sources */
  760.    prev_enabled = NULL;
  761.    ctx->Light.FirstEnabled = NULL;
  762.    for (i=0;i<MAX_LIGHTS;i++) {
  763.       ctx->Light.Light[i].NextEnabled = NULL;
  764.       if (ctx->Light.Light[i].Enabled) {
  765.          if (prev_enabled) {
  766.             prev_enabled->NextEnabled = &ctx->Light.Light[i];
  767.          }
  768.          else {
  769.             ctx->Light.FirstEnabled = &ctx->Light.Light[i];
  770.          }
  771.          prev_enabled = &ctx->Light.Light[i];
  772.       }
  773.    }
  774.  
  775.    /* Precompute some lighting stuff */
  776.    for (light = ctx->Light.FirstEnabled; light; light = light->NextEnabled) {
  777.       struct gl_material *mat = &ctx->Light.Material[0];
  778.       /* Add each light's ambient component to base color */
  779.       ctx->Light.BaseColor[0] += light->Ambient[0] * mat->Ambient[0];
  780.       ctx->Light.BaseColor[1] += light->Ambient[1] * mat->Ambient[1];
  781.       ctx->Light.BaseColor[2] += light->Ambient[2] * mat->Ambient[2];
  782.       /* compute product of light's ambient with front material ambient */
  783.       light->MatAmbient[0] = light->Ambient[0] * mat->Ambient[0];
  784.       light->MatAmbient[1] = light->Ambient[1] * mat->Ambient[1];
  785.       light->MatAmbient[2] = light->Ambient[2] * mat->Ambient[2];
  786.       /* compute product of light's diffuse with front material diffuse */
  787.       light->MatDiffuse[0] = light->Diffuse[0] * mat->Diffuse[0];
  788.       light->MatDiffuse[1] = light->Diffuse[1] * mat->Diffuse[1];
  789.       light->MatDiffuse[2] = light->Diffuse[2] * mat->Diffuse[2];
  790.       /* compute product of light's specular with front material specular */
  791.       light->MatSpecular[0] = light->Specular[0] * mat->Specular[0];
  792.       light->MatSpecular[1] = light->Specular[1] * mat->Specular[1];
  793.       light->MatSpecular[2] = light->Specular[2] * mat->Specular[2];
  794.  
  795.       /* VP (VP) = Normalize( Position ) */
  796.       COPY_3V( light->VP_inf_norm, light->Position );
  797.       NORMALIZE_3V( light->VP_inf_norm );
  798.  
  799.       /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
  800.       COPY_3V( light->h_inf_norm, light->VP_inf_norm );
  801.       light->h_inf_norm[2] += 1.0F;
  802.       NORMALIZE_3V( light->h_inf_norm );
  803.  
  804.       COPY_3V( light->NormDirection, light->Direction );
  805.       NORMALIZE_3V( light->NormDirection );
  806.  
  807.       /* Compute color index diffuse and specular light intensities */
  808.       light->dli = 0.30F * light->Diffuse[0]
  809.                  + 0.59F * light->Diffuse[1]
  810.                  + 0.11F * light->Diffuse[2];
  811.       light->sli = 0.30F * light->Specular[0]
  812.                  + 0.59F * light->Specular[1]
  813.                  + 0.11F * light->Specular[2];
  814.  
  815.    }
  816.  
  817.    /* Determine if the fast lighting function can be used */
  818.    ctx->Light.Fast = GL_TRUE;
  819.    if (    ctx->Light.BaseColor[0]<0.0F
  820.         || ctx->Light.BaseColor[1]<0.0F
  821.         || ctx->Light.BaseColor[2]<0.0F
  822.         || ctx->Light.BaseColor[3]<0.0F
  823.         || ctx->Light.Model.TwoSide
  824.         || ctx->Light.Model.LocalViewer
  825.         || ctx->Light.ColorMaterialEnabled) {
  826.       ctx->Light.Fast = GL_FALSE;
  827.    }
  828.    else {
  829.       for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
  830.          if (   light->Position[3]!=0.0F
  831.              || light->SpotCutoff!=180.0F
  832.              || light->MatDiffuse[0]<0.0F
  833.              || light->MatDiffuse[1]<0.0F
  834.              || light->MatDiffuse[2]<0.0F
  835.              || light->MatSpecular[0]<0.0F
  836.              || light->MatSpecular[1]<0.0F
  837.              || light->MatSpecular[2]<0.0F) {
  838.             ctx->Light.Fast = GL_FALSE;
  839.             break;
  840.          }
  841.       }
  842.    }
  843. }
  844.  
  845.  
  846.  
  847.  
  848.  
  849. /*
  850.  * Use current lighting/material settings to compute the RGBA colors of
  851.  * an array of vertexes.
  852.  * Input:  n - number of vertexes to process
  853.  *         vertex - array of vertex positions in eye coordinates
  854.  *         normal - array of surface normal vectors
  855.  *         twoside - 0 = front face shading only, 1 = two-sided lighting
  856.  * Output:  frontcolor - array of resulting front-face colors
  857.  *          backcolor - array of resulting back-face colors
  858.  */
  859. void gl_color_shade_vertices( GLcontext *ctx,
  860.                               GLuint n,
  861.                               GLfloat vertex[][4],
  862.                               GLfloat normal[][3],
  863.                               GLuint twoside,
  864.                               GLfixed frontcolor[][4],
  865.                               GLfixed backcolor[][4] )
  866. {
  867.    GLint side, j;
  868.    GLfloat rscale, gscale, bscale, ascale;
  869.  
  870.    /* Compute scale factor to go from floats in [0,1] to integers or fixed
  871.     * point values:
  872.     */
  873.    rscale = (GLfloat) ( (GLint) ctx->Visual->RedScale   << ctx->ColorShift );
  874.    gscale = (GLfloat) ( (GLint) ctx->Visual->GreenScale << ctx->ColorShift );
  875.    bscale = (GLfloat) ( (GLint) ctx->Visual->BlueScale  << ctx->ColorShift );
  876.    ascale = (GLfloat) ( (GLint) ctx->Visual->AlphaScale << ctx->ColorShift );
  877.  
  878.  
  879.    for (side=0;side<=twoside;side++) {
  880.       GLfloat baseR, baseG, baseB, baseA;
  881.       GLfixed sumA;
  882.       struct gl_light *light;
  883.       struct gl_material *mat;
  884.  
  885.       mat = &ctx->Light.Material[side];
  886.  
  887.       /*** Compute color contribution from global lighting ***/
  888.       baseR = mat->Emission[0] + ctx->Light.Model.Ambient[0] * mat->Ambient[0];
  889.       baseG = mat->Emission[1] + ctx->Light.Model.Ambient[1] * mat->Ambient[1];
  890.       baseB = mat->Emission[2] + ctx->Light.Model.Ambient[2] * mat->Ambient[2];
  891.  
  892.       /* Alpha is simple, same for all vertices */
  893.       baseA = mat->Diffuse[3];
  894.       sumA = (GLfixed) (CLAMP( baseA, 0.0F, 1.0F ) * ascale);
  895.  
  896.       for (j=0;j<n;j++) {
  897.          GLfloat sumR, sumG, sumB;
  898.          GLfloat nx, ny, nz;
  899.  
  900.          if (side==0) {
  901.             /* shade frontside */
  902.             nx = normal[j][0];
  903.             ny = normal[j][1];
  904.             nz = normal[j][2];
  905.          }
  906.          else {
  907.             /* shade backside */
  908.             nx = -normal[j][0];
  909.             ny = -normal[j][1];
  910.             nz = -normal[j][2];
  911.          }
  912.  
  913.          sumR = baseR;
  914.          sumG = baseG;
  915.          sumB = baseB;
  916.  
  917.          /* Add contribution from each enabled light source */
  918.          for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
  919.             GLfloat ambientR, ambientG, ambientB;
  920.             GLfloat attenuation, spot;
  921.             GLfloat VPx, VPy, VPz;  /* unit vector from vertex to light */
  922.             GLfloat n_dot_VP;       /* n dot VP */
  923.  
  924.             /* compute VP and attenuation */
  925.             if (light->Position[3]==0.0) {
  926.                /* directional light */
  927.                VPx = light->VP_inf_norm[0];
  928.                VPy = light->VP_inf_norm[1];
  929.                VPz = light->VP_inf_norm[2];
  930.                attenuation = 1.0F;
  931.             }
  932.             else {
  933.                /* positional light */
  934.                GLfloat d;     /* distance from vertex to light */
  935.                VPx = light->Position[0] - vertex[j][0];
  936.                VPy = light->Position[1] - vertex[j][1];
  937.                VPz = light->Position[2] - vertex[j][2];
  938.                d = (GLfloat) sqrt( VPx*VPx + VPy*VPy + VPz*VPz );
  939.                if (d>0.001F) {
  940.                   GLfloat invd = 1.0F / d;
  941.                   VPx *= invd;
  942.                   VPy *= invd;
  943.                   VPz *= invd;
  944.                }
  945.                attenuation = 1.0F / (light->ConstantAttenuation
  946.                            + d * (light->LinearAttenuation
  947.                            + d * light->QuadraticAttenuation));
  948.             }
  949.  
  950.             /* spotlight factor */
  951.             if (light->SpotCutoff==180.0F) {
  952.                /* not a spot light */
  953.                spot = 1.0F;
  954.             }
  955.             else {
  956.                GLfloat PVx, PVy, PVz, PV_dot_dir;
  957.                PVx = -VPx;
  958.                PVy = -VPy;
  959.                PVz = -VPz;
  960.                PV_dot_dir = PVx*light->NormDirection[0]
  961.                           + PVy*light->NormDirection[1]
  962.                           + PVz*light->NormDirection[2];
  963.                if (PV_dot_dir<=0.0F || PV_dot_dir<light->CosCutoff) {
  964.                   /* outside of cone */
  965.                   spot = 0.0F;
  966.                }
  967.                else {
  968.                   double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
  969.                   int k = (int) x;
  970.                   spot = light->SpotExpTable[k][0]
  971.                        + (x-k)*light->SpotExpTable[k][1];
  972.                }
  973.             }
  974.  
  975.             ambientR = light->Ambient[0] * mat->Ambient[0];
  976.             ambientG = light->Ambient[1] * mat->Ambient[1];
  977.             ambientB = light->Ambient[2] * mat->Ambient[2];
  978.  
  979.             /* Compute dot product or normal and vector from V to light pos */
  980.             n_dot_VP = nx * VPx + ny * VPy + nz * VPz;
  981.  
  982.             /* diffuse and specular terms */
  983.             if (n_dot_VP<=0.0F) {
  984.                /* surface face away from light, no diffuse or specular */
  985.                GLfloat t = attenuation * spot;
  986.                sumR += t * ambientR;
  987.                sumG += t * ambientG;
  988.                sumB += t * ambientB;
  989.                /* done with this light */
  990.             }
  991.             else {
  992.                GLfloat diffuseR, diffuseG, diffuseB;
  993.                GLfloat specularR, specularG, specularB;
  994.                GLfloat hx, hy, hz, n_dot_h, t;
  995.                   
  996.                /* diffuse term */
  997.                diffuseR = n_dot_VP * light->Diffuse[0] * mat->Diffuse[0];
  998.                diffuseG = n_dot_VP * light->Diffuse[1] * mat->Diffuse[1];
  999.                diffuseB = n_dot_VP * light->Diffuse[2] * mat->Diffuse[2];
  1000.  
  1001.                /* specular term */
  1002.                if (ctx->Light.Model.LocalViewer) {
  1003.                   GLfloat vx, vy, vz, vlen;
  1004.                   vx = vertex[j][0];
  1005.                   vy = vertex[j][1];
  1006.                   vz = vertex[j][2];
  1007.                   vlen = sqrt( vx*vx + vy*vy + vz*vz );
  1008.                   if (vlen>0.0001F) {
  1009.                      GLfloat invlen = 1.0F / vlen;
  1010.                      vx *= invlen;
  1011.                      vy *= invlen;
  1012.                      vz *= invlen;
  1013.                   }
  1014.                   /* h = VP + VPe */
  1015.                   hx = VPx - vx;
  1016.                   hy = VPy - vy;
  1017.                   hz = VPz - vz;
  1018.                }
  1019.                else {
  1020.                   /* h = VP + <0,0,1> */
  1021.                   hx = VPx;
  1022.                   hy = VPy;
  1023.                   hz = VPz + 1.0F;
  1024.                }
  1025.  
  1026.                /* attention: h is not normalized, done later if needed */
  1027.                n_dot_h = nx*hx + ny*hy + nz*hz;
  1028.  
  1029.                if (n_dot_h<=0.0F) {
  1030.                   specularR = 0.0F;
  1031.                   specularG = 0.0F;
  1032.                   specularB = 0.0F;
  1033.                }
  1034.                else {
  1035.                   GLfloat spec_coef;
  1036.                   /* now `correct' the dot product */
  1037.                   n_dot_h = n_dot_h / sqrt( hx*hx + hy*hy + hz*hz );
  1038.                   if (n_dot_h>1.0F) {
  1039.                      /* only happens if normal vector length > 1.0 */
  1040.                      spec_coef = pow( n_dot_h, mat->Shininess );
  1041.                   }
  1042.                   else {
  1043.                      /* use table lookup approximation */
  1044.                      int k = (int) (n_dot_h * (GLfloat) (SHINE_TABLE_SIZE-1));
  1045.                      spec_coef = mat->ShineTable[k];
  1046.                   }
  1047.                   if (spec_coef<1.0e-10) {
  1048.                      specularR = 0.0F;
  1049.                      specularG = 0.0F;
  1050.                      specularB = 0.0F;
  1051.                   }
  1052.                   else {
  1053.                      specularR = spec_coef * light->Specular[0]
  1054.                                  * mat->Specular[0];
  1055.                      specularG = spec_coef * light->Specular[1]
  1056.                                  * mat->Specular[1];
  1057.                      specularB = spec_coef * light->Specular[2]
  1058.                                  * mat->Specular[2];
  1059.                   }
  1060.                }
  1061.  
  1062.                t = attenuation * spot;
  1063.                sumR += t * (ambientR + diffuseR + specularR);
  1064.                sumG += t * (ambientG + diffuseG + specularG);
  1065.                sumB += t * (ambientB + diffuseB + specularB);
  1066.             }
  1067.  
  1068.          } /*loop over lights*/
  1069.  
  1070.          if (side==0) {
  1071.             /* clamp and convert to integer or fixed point */
  1072.             frontcolor[j][0] = (GLfixed) (CLAMP( sumR, 0.0F, 1.0F ) * rscale);
  1073.             frontcolor[j][1] = (GLfixed) (CLAMP( sumG, 0.0F, 1.0F ) * gscale);
  1074.             frontcolor[j][2] = (GLfixed) (CLAMP( sumB, 0.0F, 1.0F ) * bscale);
  1075.             frontcolor[j][3] = sumA;
  1076.          }
  1077.          else {
  1078.             /* clamp and convert to integer or fixed point */
  1079.             backcolor[j][0] = (GLfixed) (CLAMP( sumR, 0.0F, 1.0F ) * rscale);
  1080.             backcolor[j][1] = (GLfixed) (CLAMP( sumG, 0.0F, 1.0F ) * gscale);
  1081.             backcolor[j][2] = (GLfixed) (CLAMP( sumB, 0.0F, 1.0F ) * bscale);
  1082.             backcolor[j][3] = sumA;
  1083.          }
  1084.       } /*loop over vertices*/
  1085.  
  1086.    } /*for side*/
  1087. }
  1088.  
  1089.  
  1090.  
  1091. /*
  1092.  * This is an optimized version of the above function.
  1093.  */
  1094. void gl_color_shade_vertices_fast( GLcontext *ctx,
  1095.                                    GLuint n,
  1096.                                    GLfloat vertex[][4],
  1097.                                    GLfloat normal[][3],
  1098.                                    GLuint twoside,
  1099.                                    GLfixed frontcolor[][4],
  1100.                                    GLfixed backcolor[][4] )
  1101. {
  1102.    GLint j;
  1103.    GLfloat rscale, gscale, bscale, ascale;
  1104.    GLfixed A;
  1105.  
  1106.    /* Compute scale factor to go from floats in [0,1] to integers or fixed
  1107.     * point values:
  1108.     */
  1109.    rscale = (GLfloat) ( (GLint) ctx->Visual->RedScale   << ctx->ColorShift );
  1110.    gscale = (GLfloat) ( (GLint) ctx->Visual->GreenScale << ctx->ColorShift );
  1111.    bscale = (GLfloat) ( (GLint) ctx->Visual->BlueScale  << ctx->ColorShift );
  1112.    ascale = (GLfloat) ( (GLint) ctx->Visual->AlphaScale << ctx->ColorShift );
  1113.  
  1114.    /* Alpha is easy to compute, same for all vertices */
  1115.    A = (GLfixed) ( ctx->Light.BaseColor[3] * ascale);
  1116.  
  1117.    /* Loop over vertices */
  1118.    for (j=0;j<n;j++) {
  1119.       GLfloat R, G, B;
  1120.       GLfloat nx, ny, nz;
  1121.       struct gl_light *light;
  1122.  
  1123.       /* the normal vector */
  1124.       nx = normal[j][0];
  1125.       ny = normal[j][1];
  1126.       nz = normal[j][2];
  1127.  
  1128.       /* base color from global illumination and enabled light's ambient */
  1129.       R = ctx->Light.BaseColor[0];
  1130.       G = ctx->Light.BaseColor[1];
  1131.       B = ctx->Light.BaseColor[2];
  1132.  
  1133.       /* Add contribution from each light source */
  1134.       for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
  1135.          GLfloat n_dot_VP;     /* n dot VP */
  1136.  
  1137.          n_dot_VP = nx * light->VP_inf_norm[0]
  1138.                   + ny * light->VP_inf_norm[1]
  1139.                   + nz * light->VP_inf_norm[2];
  1140.  
  1141.          /* diffuse and specular terms */
  1142.          if (n_dot_VP>0.0F) {
  1143.             GLfloat n_dot_h;
  1144.  
  1145.             /** add diffuse term **/
  1146.             R += n_dot_VP * light->MatDiffuse[0];
  1147.             G += n_dot_VP * light->MatDiffuse[1];
  1148.             B += n_dot_VP * light->MatDiffuse[2];
  1149.  
  1150.             /** specular term **/
  1151.             /* dot product of n and h_inf_norm */
  1152.             n_dot_h = nx * light->h_inf_norm[0]
  1153.                     + ny * light->h_inf_norm[1]
  1154.                     + nz * light->h_inf_norm[2];
  1155.             if (n_dot_h>0.0F) {
  1156.                if (n_dot_h>1.0F) {
  1157.                   /* only happens if Magnitude(n) > 1.0 */
  1158.                   GLfloat spec_coef = pow( n_dot_h,
  1159.                                            ctx->Light.Material[0].Shininess );
  1160.                   if (spec_coef>1.0e-10F) {
  1161.                      R += spec_coef * light->MatSpecular[0];
  1162.                      G += spec_coef * light->MatSpecular[1];
  1163.                      B += spec_coef * light->MatSpecular[2];
  1164.                   }
  1165.                }
  1166.                else {
  1167.                   /* use table lookup approximation */
  1168.                   int k = (int) (n_dot_h * (GLfloat) (SHINE_TABLE_SIZE-1));
  1169.                   GLfloat spec_coef = ctx->Light.Material[0].ShineTable[k];
  1170.                   R += spec_coef * light->MatSpecular[0];
  1171.                   G += spec_coef * light->MatSpecular[1];
  1172.                   B += spec_coef * light->MatSpecular[2];
  1173.                }
  1174.             }
  1175.          }
  1176.  
  1177.       } /*loop over lights*/
  1178.  
  1179.       /* clamp and convert to integer or fixed point */
  1180.       frontcolor[j][0] = (GLfixed) (MIN2( R, 1.0F ) * rscale);
  1181.       frontcolor[j][1] = (GLfixed) (MIN2( G, 1.0F ) * gscale);
  1182.       frontcolor[j][2] = (GLfixed) (MIN2( B, 1.0F ) * bscale);
  1183.       frontcolor[j][3] = A;
  1184.  
  1185.    } /*loop over vertices*/
  1186. }
  1187.  
  1188.  
  1189.  
  1190. /*
  1191.  * Use current lighting/material settings to compute the color indexes
  1192.  * for an array of vertices.
  1193.  * Input:  n - number of vertices to shade
  1194.  *         vertex - array of [n] vertex position in viewing coordinates
  1195.  *         normal - array of [n] surface normal vector
  1196.  *         twoside - 0 = front face shading only, 1 = two-sided lighting
  1197.  * Output:  frontindex - resulting array of [n] front-face color indexes
  1198.  *          backindex - resulting array of [n] back-face color indexes
  1199.  */
  1200. void gl_index_shade_vertices( GLcontext *ctx,
  1201.                               GLuint n,
  1202.                               GLfloat vertex[][4],
  1203.                               GLfloat normal[][3],
  1204.                               GLuint twoside,
  1205.                               GLuint frontindex[],
  1206.                               GLuint backindex[] )
  1207. {
  1208.    GLint side, j;
  1209.    GLuint *output_index;
  1210.  
  1211.    for (side=0;side<=twoside;side++) {
  1212.       struct gl_material *mat = &ctx->Light.Material[side];
  1213.  
  1214.       if (side==0) {
  1215.          output_index = frontindex;
  1216.       }
  1217.       else {
  1218.          output_index = backindex;
  1219.       }
  1220.  
  1221.       /* loop over vertices */
  1222.       for (j=0;j<n;j++) {
  1223.          GLfloat index;
  1224.          GLfloat diffuse, specular;  /* accumulated diffuse and specular */
  1225.          GLfloat nx, ny, nz;  /* normal vector */
  1226.          struct gl_light *light;
  1227.  
  1228.          if (side==0) {
  1229.             /* shade frontside */
  1230.             nx = normal[j][0];
  1231.             ny = normal[j][1];
  1232.             nz = normal[j][2];
  1233.          }
  1234.          else {
  1235.             /* shade backside */
  1236.             nx = -normal[j][0];
  1237.             ny = -normal[j][1];
  1238.             nz = -normal[j][2];
  1239.          }
  1240.  
  1241.          diffuse = specular = 0.0F;
  1242.  
  1243.          /* Accumulate diffuse and specular from each light source */
  1244.          for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
  1245.             GLfloat attenuation;
  1246.             GLfloat lx, ly, lz;  /* unit vector from vertex to light */
  1247.             GLfloat l_dot_norm;  /* dot product of l and n */
  1248.  
  1249.             /* compute l and attenuation */
  1250.             if (light->Position[3]==0.0) {
  1251.                /* directional light */
  1252.                /* Effectively, l is a vector from the origin to the light. */
  1253.                lx = light->VP_inf_norm[0];
  1254.                ly = light->VP_inf_norm[1];
  1255.                lz = light->VP_inf_norm[2];
  1256.                attenuation = 1.0F;
  1257.             }
  1258.             else {
  1259.                /* positional light */
  1260.                GLfloat d;     /* distance from vertex to light */
  1261.                lx = light->Position[0] - vertex[j][0];
  1262.                ly = light->Position[1] - vertex[j][1];
  1263.                lz = light->Position[2] - vertex[j][2];
  1264.                d = (GLfloat) sqrt( lx*lx + ly*ly + lz*lz );
  1265.                if (d>0.001F) {
  1266.                   GLfloat invd = 1.0F / d;
  1267.                   lx *= invd;
  1268.                   ly *= invd;
  1269.                   lz *= invd;
  1270.                }
  1271.                attenuation = 1.0F / (light->ConstantAttenuation
  1272.                              + d * (light->LinearAttenuation
  1273.                              + d * light->QuadraticAttenuation));
  1274.             }
  1275.  
  1276.             l_dot_norm = lx*nx + ly*ny + lz*nz;
  1277.  
  1278.             if (l_dot_norm>0.0F) {
  1279.                GLfloat spot_times_atten;
  1280.  
  1281.                /* spotlight factor */
  1282.                if (light->SpotCutoff==180.0F) {
  1283.                   /* not a spot light */
  1284.                   spot_times_atten = attenuation;
  1285.                }
  1286.                else {
  1287.                   GLfloat v[3], dot;
  1288.                   v[0] = -lx;  /* v points from light to vertex */
  1289.                   v[1] = -ly;
  1290.                   v[2] = -lz;
  1291.                   dot = DOT3( v, light->NormDirection );
  1292.                   if (dot<=0.0F || dot<light->CosCutoff) {
  1293.                      /* outside of cone */
  1294.                      spot_times_atten = 0.0F;
  1295.                   }
  1296.                   else {
  1297.                      double x = dot * (EXP_TABLE_SIZE-1);
  1298.                      int k = (int) x;
  1299.                      GLfloat spot = light->SpotExpTable[k][0]
  1300.                                   + (x-k)*light->SpotExpTable[k][1];
  1301.                      spot_times_atten = spot * attenuation;
  1302.                   }
  1303.                }
  1304.  
  1305.                /* accumulate diffuse term */
  1306.                diffuse += l_dot_norm * light->dli * spot_times_atten;
  1307.  
  1308.                /* accumulate specular term */
  1309.                {
  1310.                   GLfloat hx, hy, hz, dot, spec_coef;
  1311.  
  1312.                   /* specular term */
  1313.                   if (ctx->Light.Model.LocalViewer) {
  1314.                      GLfloat vx, vy, vz, vlen;
  1315.                      vx = vertex[j][0];
  1316.                      vy = vertex[j][1];
  1317.                      vz = vertex[j][2];
  1318.                      vlen = sqrt( vx*vx + vy*vy + vz*vz );
  1319.                      if (vlen>0.0001F) {
  1320.                         GLfloat invlen = 1.0F / vlen;
  1321.                         vx *= invlen;
  1322.                         vy *= invlen;
  1323.                         vz *= invlen;
  1324.                      }
  1325.                      hx = lx - vx;
  1326.                      hy = ly - vy;
  1327.                      hz = lz - vz;
  1328.                   }
  1329.                   else {
  1330.                      hx = lx;
  1331.                      hy = ly;
  1332.                      hz = lz + 1.0F;
  1333.                   }
  1334.                   /* attention: s is not normalized, done later if necessary */
  1335.                   dot = hx*nx + hy*ny + hz*nz;
  1336.  
  1337.                   if (dot<=0.0F) {
  1338.                      spec_coef = 0.0F;
  1339.                   }
  1340.                   else {
  1341.                      /* now `correct' the dot product */
  1342.                      dot = dot / sqrt(hx*hx + hy*hy + hz*hz);
  1343.                      if (dot>1.0F) {
  1344.                         spec_coef = pow( dot, mat->Shininess );
  1345.                      }
  1346.                      else {
  1347.                         int k = (int) (dot * (GLfloat)(SHINE_TABLE_SIZE-1));
  1348.                         spec_coef = mat->ShineTable[k];
  1349.                      }
  1350.                   }
  1351.                   specular += spec_coef * light->sli * spot_times_atten;
  1352.                }
  1353.             }
  1354.  
  1355.          } /*loop over lights*/
  1356.  
  1357.          /* Now compute final color index */
  1358.          if (specular>1.0F) {
  1359.             index = mat->SpecularIndex;
  1360.          }
  1361.          else {
  1362.             GLfloat d_a, s_a;
  1363.             d_a = mat->DiffuseIndex - mat->AmbientIndex;
  1364.             s_a = mat->SpecularIndex - mat->AmbientIndex;
  1365.  
  1366.             index = mat->AmbientIndex
  1367.                   + diffuse * (1.0F-specular) * d_a
  1368.                   + specular * s_a;
  1369.             if (index>mat->SpecularIndex) {
  1370.                index = mat->SpecularIndex;
  1371.             }
  1372.          }
  1373.          output_index[j] = (GLuint) (GLint) index;
  1374.  
  1375.       } /*for vertex*/
  1376.  
  1377.    } /*for side*/
  1378. }
  1379.